package org.zk.intercepter;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.zk.entity.User;
import org.zk.util.RedisUtil;

import java.util.Map;

/**
 * 说明:aop拦截器，拦截了Service中对应的查询方法。
 *
 * @姚文斌
 * @create 2019-11-24 上午 10:57
 */
public class CacheInteceptor implements MethodInterceptor {//实现方法级别的拦截器接口
    //引入redis工具类
    private RedisUtil redisUtil;

    public RedisUtil getRedisUtil() {
        return redisUtil;
    }

    public void setRedisUtil(RedisUtil redisUtil) {
        this.redisUtil = redisUtil;
    }

    //缓存有效期
    private Long defaultCacheExpireTime=3600L;


    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        Object value=null;
        //获得类名
        String targetName=methodInvocation.getThis().getClass().getName();
        //获得方法名
        String methodName=methodInvocation.getMethod().getName();
        //获得Service中对应方法的参数集合
        Object []arguments=methodInvocation.getArguments();
        Map<String,Object>maps= (Map<String, Object>) arguments[0];
        //从参数集合中取出pageSize和pageNum，调用自己封装的方法构造出Redis中要存入的数据的key
        String pageSize=String.valueOf(maps.get("pageSize"));
        String pageNum= String.valueOf(maps.get("pageNum"));
        User user= (User) maps.get("user");
        String userName=user.getUserName();
        String userAge=user.getAge();
        Object[]args={pageNum+":"+pageSize+"_"+userName+"_"+userAge};
        final String key=getCacheKey(targetName,methodName,args);
        //进行查询时，如果缓存中有对应的key就读取，没有就写入
        if (redisUtil.exists(key)){
            return redisUtil.get(key);
        }
        value = methodInvocation.proceed();//继续进行
        if (value!=null){
            final String tkey=key;
            final Object tval=value;
            //开启一个独立的线程，开始写入Redis
            new Thread(new Runnable() {
                @Override
                public void run() {
                    redisUtil.set(tkey,tval,defaultCacheExpireTime);
                }
            }).start();
        }

        return value;
    }
    //封装一个方法用来构造缓存的key
    public String getCacheKey(String targetName,String methodName,Object[]args){
        StringBuffer sb=new StringBuffer();
        sb.append(targetName).append("_").append(methodName);
        if ((args!=null)&&(args.length!=0)){
            for (int i=0;i<args.length;i++){
                sb.append("_").append(args[i]);
            }
        }
        return sb.toString();
    }
}
